﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITProject.Domain.Entities;
using ITProject.Domain;

namespace ITProject.Repository.Abstract
{
    /// <summary>
    /// Ineterfejs pozwalający na operacje na projektach.
    /// Autor: Jakub Szatkowski
    /// </summary>
    public interface IProjectRepository
    {
        /// <summary>
        /// Metoda pozwalająca na dodawanie projektów.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="project">Projekt do dodania.</param>
        /// <param name="userName">Login użytkownika dodającego projekt.</param>
        void Add(Project project,string userName);

        /// <summary>
        /// Metoda pozwalająca edytować opisy i logo projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="editedProject">Wyedytowany projekt.</param>
        void EditProject(Project editedProject);

        /// <summary>
        /// Metoda pozwala zwrócić listę wszystkich projektów w serwisie ITProject.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <returns>Kolekcja projektów.</returns>
        IEnumerable<Project> GetProjects();

        /// <summary>
        /// Metoda pozwalająca pobrać encję projektu na podstawie jego nazwy.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="name">Nazwa projektu.</param>
        /// <returns>Obiekt encji projektu.</returns>
        Project GetProjectByName(string name);
        bool IsUserInProject(int idp, int idu);
        /// <summary>
        /// Metoda pozwalająca pobrać użytkowników projektu wraz z rolami.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="users">Użytkownicy projektu</param>
        /// <param name="roles">Role użytkowników projektu.</param>
        /// <param name="projectName">Nazwa projektu</param>
        void GetProjectUsers(out User[] users, out UserRole[] roles,string projectName);

        /// <summary>
        /// Metoda pozwalająca na pobranie roli użytkownika w danym projekcie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu</param>
        /// <param name="userName">Login użytkownika</param>
        /// <returns>Rola użytkownika w projekcie</returns>
        UserRole GetProjectUserRole(string projectName, string userName);

        /// <summary>
        /// Metoda pozwala pobrać identyfikatory zaproszonych do projektu użytkowników.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu</param>
        /// <returns>Identyfikatory zaproszonych do tego projektu użytkowników.</returns>
        int[] GetIdInvitedUsers(string projectName);

        /// <summary>
        /// Metoda pozwalająca zaprosić użytkownika do projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu</param>
        /// <param name="userId">Id zapraszanego użytkownika</param>
        void Invite(string projectName, int userId);

        /// <summary>
        /// Metoda pozwalająca zaprosić użytkownika do projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Identyfikator projektu.</param>
        /// <param name="userId">Id zapraszanego użytkownika.</param>
        void Invite(int projectId, int userId);

        /// <summary>
        /// Metoda pozwala pobrać identyfikator projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <returns>Identyfikator projektu.</returns>
        int GetProjectId(string projectName);

        /// <summary>
        /// Metoda dodaje użytkownika do projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <param name="userId">Identyfikator użytkownika.</param>
        void AddUserToProject(int projectId, int userId);

        /// <summary>
        /// Metoda pozwala na usunięcie użytkownika projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <param name="userId">Identyfikator użytkownika.</param>
        /// <returns>Prawda jeśli użytkownika został usunięty z projektu, fałsz jeśli nie ma użytkownika w projekcie.</returns>
        bool DeleteUserFromProject(int projectId, int userId);

        /// <summary>
        /// Akceptacja zaproszenia uczestnictwa w projekcie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <param name="userId">Identyfikator użytkownika.</param>
        /// <returns>Prawda jeśli zaproszenie istnieje.</returns>
        bool AcceptInvitation(int projectId, int userId);

        /// <summary>
        /// Odrzucenie zaproszenia uczestnictwa w projekcie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <param name="userId">Identyfikator użytkownika.</param>
        /// <returns>Prawda jeśli zaproszenie istnieje.</returns>
        bool RejectInvitation(int projectId, int userId);

        /// <summary>
        /// Metoda pozwala pobrać encję projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Identyfikator projektu.</param>
        /// <returns>Obiekt projektu.</returns>
        Project GetProjectById(int projectId);

        void GetUserProject(int idUser, out List<string> uproject,out List<string> sproject);

        /// <summary>
        /// Metoda pozwala na pobranie obiektu encji właściciela projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectName">Nazwa projektu</param>
        /// <returns>Właściciel projektu</returns>
        User GetProjectOwner(string projectName);

        /// <summary>
        /// Metoda pozwalająca pobrać wszystkie zespoły w danym projekcie.
        /// </summary>
        /// <param name="projectName">Nazwa projektu.</param>
        /// <returns>Kolekacja zespołów projektu.</returns>
        IEnumerable<Team> GetProjectTeams(string projectName);

        /// <summary>
        /// Metoda pozwalająca na dodanie nowego zespołu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="team">Obiekt zespołu.</param>
        void AddNewTeam(Team team);

         /// <summary>
        /// Funkcja zapisuje zmiane roli uzytkownika
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="idUser">id uzytkownika</param>
        /// <param name="newRole">nowa rola</param>
        void EditRole(int idUser, int newRole, int idProject);

        /// <summary>
        /// Metoda zwraca id zespolu
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="treamName"></param>
        /// <returns></returns>
        int GetTeamId(string teamName,int idproject);

        /// <summary>
        /// Zwraca loginy uzytkownikow w projekcie
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="idteam"></param>
        /// <returns></returns>
        List<String> GetTeamUsers(int idteam);

         /// <summary>
        /// Metoda zwraca loginy uzytkownikow projektu
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="idproject"></param>
        /// <returns></returns>
        List<String> GetProjectUsersLogin(int idproject);

        /// <summary>
        /// Metoda dodaje uzytkownika do projektu
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="idteamu"></param>
        /// <param name="iduser"></param>
        void AddUserToTeam(int idteamu, int iduser);

        /// <summary>
        /// Metoda usuwa osobnika z projektu
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="idteamu"></param>
        /// <param name="iduser"></param>
        /// <returns></returns>
        bool RemoveUserFromTeam(int idteamu, int iduser);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="projectName"></param>
        /// <param name="tems"></param>
        /// <param name="leaders"></param>
        /// <param name="users"></param>
        void GetProjectTeams(string projectName, out Team[] tems, out string[] leaders, out User[][] users);

        /// <summary>
        /// Metoda zwraca nazwe lidera grupy
        /// Natalia Wyczislok
        /// </summary>
        /// <param name="idTeam"></param>
        /// <returns></returns>
        string GetTeamLeader(int idTeam);

        /// <summary>
        /// Metoda pozwala pobrać obiekt encji zespołu poprzez podanie jego identyfikatora.
        /// </summary>
        /// <param name="idTeam">Identyfikator zespołu.</param>
        /// <returns>Zespół.</returns>
        Team GetTeamById(int idTeam);

        /// <summary>
        /// Metoda pozwalająca na edycję zespołu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="team">Zespół do edycji z nowymi danymi.</param>
        void EditTeam(Team team);

        List<Project> GetProjectByOwnerLogin(string login);
        List<ForumTopic> GetProjectForumTopics(int projectId);
        ForumTopic AddForumTopic(string topic, int autorId, int projectId);
        void AddPost(string content, int autorId, int TopicId);
        List<Post> GetTopicPosts(int topicID);
        string GetTopicName(int topicID);
        int GetProjectIDByTopic(int idtopic);

        #region Funkcjonalności związane z Releasami

        /// <summary>
        /// Metoda pozwala dodać nową werję do projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="release">Wersja.</param>
        /// <param name="userId">Identyfikator użytkownika dodającego wersje.</param>
        void AddNewRelease(Release release, int userId);

        /// <summary>
        /// Metoda pozwalająca pobrać wszystkie wersje stworzone w danym projekcie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Tablica z wersjami</returns>
        Release[] GetProjectReleases(int projectId);

        /// <summary>
        /// Metoda pozwala pobrać dane o wybranej wersji konkretnego projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="releaseName">Nazwa wersji.</param>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Obiekt wersji.</returns>
        Release GetReleaseByName(string releaseName, int projectId);

        /// <summary>
        /// Metoda pozwala pobrać dane o wybranej wersji.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="releaseId">Identyfikator wersji.</param>
        /// <returns>Obiekt wersji.</returns>
        Release GetReleaseById(int releaseId);

        /// <summary>
        /// Metoda pozwala zmienić status wybranej wersji.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="release">Dane o wersji.</param>
        /// <param name="newStatus">Nowy status.</param>
        /// <param name="comment">Komentarz zmiany statusu.</param>
        /// <param name="userId">Identyfikator użytkownika zmieniającego status.</param>
        void ChangeReleaseStatus(Release release, Status newStatus, string comment, int userId);

        /// <summary>
        /// Metoda pozwalająca wyedytować dane o wersji.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="release">Nowe dane o wersji.</param>
        void EditRelease(Release release);

        /// <summary>
        /// Metoda pozwala pobrać wszystkei zmiany statusu danej wersji.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="release">Obiekt wersji.</param>
        /// <param name="statsusChanges">Tablica zmian statusów wersji.</param>
        /// <param name="users">Tablica użytkowników zmieniających status.</param>
        void GetReleaseStatusChanges(Release release, out StatusChange[] statsusChanges, out string[] users);

        #endregion

        #region Wymagania funkcjonalne

        /// <summary>
        /// Metoda pozwalająca pobrać kolekcję wymagań funkcjonalnych danego projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Tablica wymagań funkcjonalnych projektu.</returns>
        FunctionalRequirement[] GetProjectFunctionalRequirements(int projectId);

        /// <summary>
        /// Metoda pozwalająca na dodanie do bazy nowego wymagania funkcjonalnego.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="fc">Obiekt klasy encji wymagania funkcjonalnego.</param>
        /// <returns>Automatycznie wygenerowany przez baze indetyfikator nowego wymagania w bazie.</returns>
        int AddFunctionalRequirement(FunctionalRequirement fc);

        /// <summary>
        /// Metoda pozwala pobrać największe identyfikator istniejący w tabeli scenariuszy.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <returns>Identyfikator scenariusza.</returns>
        int? GetMaxScenarioId();

        /// <summary>
        /// Metoda zapisuje do bazy scenariusze wymagania funkcjonalnego.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="scenarios">Lista scenariuszy do zapisania.</param>
        void AddScenarios(List<Scenario> scenarios);

        /// <summary>
        /// Metoda pobierające wszystkie scenariusze danego wymagania funkcjonalnego.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="requirementId">Identyfikator wymagania.</param>
        /// <returns>Tablica scenariuszy wymagania.</returns>
        Scenario[] GetRequirementScenarios(int requirementId);

        /// <summary>
        /// Metoda pozwalająca na usuwanie wybranego wymagania funkcjonalnego.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="requirementId">Identyfikator wymagania.</param>
        void DeleteFunctionalRequirement(int requirementId);

        /// <summary>
        /// Metoda zwracająca wymaganie funckjonalne o odpowiednim identyfikatorze.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="requirementId">Identyfikator wymagania.</param>
        /// <returns>Obiekt wymagania funkcjonalnego.</returns>
        FunctionalRequirement GetFunctionalRequirementById(int requirementId);

        #endregion

        #region Funckjonalności

        /// <summary>
        /// Metoda zwracająca wszystkie funkcjonalności w projekcie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId"></param>
        /// <returns>Tablica funkcjonalności.</returns>
        Feature[] GetProjectFeatures(int projectId);

        /// <summary>
        /// Metoda pozwala pobrać zespół do którego przypisana jest dana funkcjonalność.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="featureId">Identyfikator funkcjonalności.</param>
        /// <returns>Zespoł.</returns>
        Team GetFeatureTeamByFeatureId(int featureId);

        /// <summary>
        /// Metoda pozwala pobrać użytkownika do którego przypisana jest dana funkcjonalność.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="featureId">Identyfikator funkcjonalności.</param>
        /// <returns>Użytkownik.</returns>
        User GetFeatureUserByFeatureId(int featureId);

        /// <summary>
        /// Metoda pozwala dodać nową funkcjonalność do projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="feature">Obiekt funkcjonalności.</param>
        /// <param name="receiver">Odbiorca funkcjonalności, czyli ktoś kto ma w projekcie tę funkcjonalność wykonać (uczestnik lub zespół).</param>
        /// <param name="creator">Identyfikator użytkownika, który dodał funkcjonalność.</param>
        void AddNewFeature(Feature feature, string receiver,int creator);

        /// <summary>
        /// Metoda pozwalająca pobrać funkcjonalność przy pomocy identyfikatora funkcjonalności.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="featureId">Identyfikator funkcjonalności.</param>
        /// <returns>Funkcjonalność.</returns>
        Feature GetFeatureById(int featureId);

        /// <summary>
        /// Metoda pozwalająca edytować funkcjonalność.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="feature">Nowe dane funkcjonalności.</param>
        /// <param name="featureTeam">Zespół przypisany do funkcjonalności.</param>
        /// <param name="featureUser">Uczestnik przypisany do funkcjonalności.</param>
        void EditFeature(Feature feature, string featureTeam, string featureUser);

        /// <summary>
        /// Metoda zmieniająca status funkcjonalności i zapisująca dokonane zmiany.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="feature">Obiekt funkcjonalności.</param>
        /// <param name="statusChange">Obiekt zmiany statusu.</param>
        void ChangeFeatureStatus(Feature feature, StatusChange statusChange);

        /// <summary>
        /// Metoda pozwala pobrać wszystkei zmiany statusu danej funkcjonalności.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="release">Obiekt funkcjonalności.</param>
        /// <param name="statsusChanges">Tablica zmian statusów funkcjonalności.</param>
        /// <param name="users">Tablica użytkowników zmieniających status.</param>
        void GetFeatureStatusChanges(Feature feature, out StatusChange[] statsusChanges, out string[] users);

        /// <summary>
        /// Metoda zwracająca wszystkei funkcjonalności przypisane do danego uczestnika z danego projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="userId">Identyfikator użytkownika.</param>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Tablica funkcjonalności przypisanych do użytkownika.</returns>
        Feature[] GetUserFeatures(int userId, int projectId);

        /// <summary>
        /// Metoda zwracająca wszystkei funkcjonalności przypisane do danego zespołu z danego projektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="teamId">Identyfikator zespołu.</param>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Tablica funkcjonalności przypisanych do zespołu.</returns>
        Feature[] GetTeamFeatures(int teamId, int projectId);

        /// <summary>
        /// Metoda pozwala pobrać funkcjonalność na podstawie jej nazwy i projektu do którego należy.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="featureName">Nazwa funkcjonalności.</param>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Funkcjonalność.</returns>
        Feature GetFeatureByName(string featureName, int projectId);

        #endregion

        #region Taski

        /// <summary>
        /// Metoda do pobrania wszystkich zadań będących w projekcie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Tablica zadań.</returns>
        Task[] GetProjectTasks(int projectId);

        /// <summary>
        /// Metoda pozwalająca dodać do bazy danych nowe zadanie.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="task">Zadanie.</param>
        /// <param name="creatorId">Identyfikator uczestnika dodającego zadanie.</param>
        void AddNewTask(Task task, int creatorId);

        /// <summary>
        /// Metoda pozwalająca pobrać obiekt zadania na podstawie identyfikatora.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="taskId">Identyfikator zadania.</param>
        /// <returns>Obiket zadania.</returns>
        Task GetTaskById(int taskId);

        /// <summary>
        /// Metoda do edycji zadania.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="task">Wyedytoane zadanie.</param>
        void EditTask(Task task);

        /// <summary>
        /// Metoda pozwala pobrać zadania przypisane do użytkownika w ramach konkretnego prpjektu.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="userId">Identyfikator uczestnika.</param>
        /// <param name="projectId">Identyfikator projektu.</param>
        /// <returns>Tablica zadań do wykonania.</returns>
        Task[] GetUserTasks(int userId, int projectId);

        /// <summary>
        /// Metoda pozwala pobrać wszystkie zmiany statusu danego zadania.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="release">Obiekt zadania.</param>
        /// <param name="statsusChanges">Tablica zmian statusów zadania.</param>
        /// <param name="users">Tablica użytkowników zmieniających status.</param>
        void GetTaskStatusChanges(Task task, out StatusChange[] statsusChanges, out string[] users);

        /// <summary>
        /// Metoda zmieniająca status zadania i zapisująca dokonane zmiany.
        /// Autor: Jakub Szatkowski
        /// </summary>
        /// <param name="feature">Obiekt zadania.</param>
        /// <param name="statusChange">Obiekt zmiany statusu.</param>
        void ChangeTaskStatus(Task task, StatusChange statusChange);

        string GetUserbyTaskID(int taskid);
        #endregion

        /// <summary>
        /// Natalia Wyczislok
        /// Funkcja pobierajaca wszystkie komentarze danego projektu
        /// </summary>
        /// <param name="id_project"></param>
        /// <returns></returns>
        Comment[] GetProjectComment(int id_project);
        void AddComment(Comment c);

        /// <summary>
        /// Pobranie zespołów, którymi zarządza dany lider z danego projektu.
        /// </summary>
        /// <param name="projectId"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        Team[] GetTeamsManageByUser(int projectId,int userId);

        ForumTopic GetTopicById(int id);
    }
}

